package com.wheatek.wtklib.net

import android.app.Application
import android.graphics.BitmapFactory
import com.google.gson.Gson
import com.wheatek.wtklib.net.callback.HttpCallback
import com.wheatek.wtklib.net.callback.ICallBack
import com.wheatek.wtklib.net.exception.RequestException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.HttpUrl
import okhttp3.MediaType
import okhttp3.Request
import okhttp3.RequestBody
import org.json.JSONObject


object HttpUtils {

    private var mContext: Application? = null
    private var mBaseUrl: String? = null
    private var mCer: String? = null

    fun init(context: Application, baseUrl: String) {
        init(context, baseUrl, "")
    }

    fun init(context: Application, baseUrl: String, cer: String) {
        mContext = context
        mBaseUrl = baseUrl
        this.mCer = cer
    }

    fun getBaseUrl(): String {
        return mBaseUrl ?: ""
    }

    // get请求
    suspend fun <T> get(
            url: String, callBack: HttpCallback<T>
    ) {
        get(url, null, null, callBack)
    }

    suspend fun <T> get(
            url: String, param: HashMap<String, Any>?, callBack: ICallBack<T>
    ) {
        get(url, param, null, callBack)
    }

    suspend fun <T> get(
            url: String,
            param: HashMap<String, Any>?,
            headers: HashMap<String, String>?,
            callBack: ICallBack<T>
    ) {
        val newUrl = if (url.startsWith("http")) url else mBaseUrl + url

        val urlBuilder = HttpUrl.parse(newUrl)?.newBuilder()

        param?.let {
            it.keys.forEach { key ->
                urlBuilder?.addQueryParameter(key, it[key].toString())
            }
        }
        val httpUrl = urlBuilder?.build()
        execRequest("GET", httpUrl, headers, null, callBack)
    }

    // post请求
    suspend fun <T> post(
            url: String, param: HashMap<String, Any>, callBack: ICallBack<T>
    ) {
        val requestBody = RequestBody.create(
                MediaType.parse("application/json; charset=utf-8"),
                Gson().toJson(param)
        )
        val newUrl = if (url.startsWith("http")) url else mBaseUrl + url

        val httpUrl = HttpUrl.parse(newUrl)?.newBuilder()?.build()
        execRequest("POST", httpUrl, null, requestBody, callBack)
    }

    suspend fun <T> post(
            url: String,
            param: HashMap<String, Any>,
            headers: HashMap<String, String>,
            callBack: ICallBack<T>
    ) {
        val requestBody = RequestBody.create(
                MediaType.parse("application/json; charset=utf-8"),
                Gson().toJson(param)
        )
        val httpUrl = HttpUrl.parse(url)?.newBuilder()?.build()
        execRequest("POST", httpUrl, headers, requestBody, callBack)
    }


    private suspend fun <T> execRequest(
            method: String,
            url: HttpUrl?,
            headers: HashMap<String, String>?,
            requestBody: RequestBody?,
            callBack: ICallBack<T>
    ) {
        if (mContext == null) {
            throw NullPointerException("you must init HttpUtils")
        }
        val requestBuilder = Request.Builder().run {
            url(url)
            method(method, requestBody)
        }
        headers?.keys?.forEach {
            requestBuilder.addHeader(it, headers[it])
        }

        val request = requestBuilder.build()

        OkHttpUtils.getClient(mContext!!, mCer).newCall(request).execute().use { response ->
            val body = response.body()?.string() ?: throw RequestException("数据为空")
            val jsonObject = JSONObject(body)
            val code = jsonObject.get("code")
            when (code.toString()) {
                "0000",
                "200",
                "201" -> {
                    withContext(Dispatchers.Main) {
                        callBack.onNext(body)
                    }
                }
                "444" -> {
                    callBack.onNotLogin()
                }
                else -> {
                    throw RequestException("未知异常：$code")
                }
            }
        }
    }

    public suspend fun <T> loadImg(
            url: String?,
            callBack: ICallBack<T>
    ) {
        if (mContext == null) {
            throw NullPointerException("you must init HttpUtils")
        }
        val requestBuilder = Request.Builder().run {
            url(url)
            get()
        }

        val request = requestBuilder.build()

        OkHttpUtils.getClient(mContext!!, mCer).newCall(request).execute().use { response ->
            val bytes = response.body()?.bytes() ?: throw RequestException("数据为空")
            val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
            callBack.onSuccess(bitmap as T, "200", "成功")
        }
    }
}